package controller

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"reflect"
	"strings"

	"strconv"

	"github.com/cyfqyb/fiber_demo/dao"
	"github.com/cyfqyb/fiber_demo/models"
	"github.com/gofiber/fiber/v2"
)

type RouteConfig struct {
	Path      string        `json:"path"`
	Group     string        `json:"group"`
	Method    string        `json:"method"`
	Operation string        `json:"operation"`
	Model     string        `json:"model"`
	Params    []ParamConfig `json:"params"`
	Children  []RouteConfig `json:"children"`
}

type ParamConfig struct {
	Name   string `json:"name"`
	Source string `json:"source"`
	Type   string `json:"type"`
	Enable bool   `json:"enable"`
}

func init() {
	RegisterRoute(func(app *fiber.App) {
		AutoRouterReg(app)
	})
}

func AutoRouterReg(app *fiber.App) {
	configs, err := LoadRouteConfigs()
	if err != nil {
		log.Fatalf("Failed to load route configs: %v", err)
	}

	for _, cfg := range configs {
		switch v := cfg.(type) {
		case map[string]interface{}:
			if group, ok := v["group"].(string); ok {
				children, ok := v["children"].([]interface{})
				if ok {
					groupInstance := app.Group(group)
					for _, child := range children {
						childCfg, err := parseRouteConfig(child)
						if err != nil {
							log.Printf("Failed to parse route config: %v", err)
							continue
						}
						handler := createHandler(childCfg)
						registerRoute(groupInstance, childCfg, handler)
					}
				}
			} else {
				routeCfg, err := parseRouteConfig(v)
				if err != nil {
					log.Printf("Failed to parse route config: %v", err)
					continue
				}
				handler := createHandler(routeCfg)
				registerRoute(app, routeCfg, handler)
			}
		}
	}
}

// createModelInstance 根据模型名称创建模型实例
func createModelInstance(modelName string) (interface{}, error) {
	modelType, exists := models.ModelMap[modelName]
	if !exists {
		return nil, fmt.Errorf("unsupported model: %s", modelName)
	}
	return reflect.New(modelType).Interface(), nil
}

// setModelID 使用反射设置模型的 ID
func setModelID(model interface{}, id uint64) error {
	modelValue := reflect.ValueOf(model).Elem()
	modelField := modelValue.FieldByName("Model")
	if !modelField.IsValid() {
		return fmt.Errorf("model does not have 'Model' field")
	}
	idField := modelField.FieldByName("ID")
	if !idField.IsValid() || !idField.CanSet() {
		return fmt.Errorf("model does not have a settable 'ID' field")
	}
	idField.SetUint(id)
	return nil
}

// setModelField 函数用于动态设置模型的字段值
func setModelField(model interface{}, fieldName string, value interface{}) error {
	// 获取模型的反射值
	modelValue := reflect.ValueOf(model)
	// 检查模型是否为指针类型，如果是指针则获取其指向的值
	if modelValue.Kind() != reflect.Ptr || modelValue.IsNil() {
		return fmt.Errorf("model must be a non - nil pointer")
	}
	modelValue = modelValue.Elem()

	// 获取要设置的字段
	field := modelValue.FieldByName(fieldName)
	if !field.IsValid() {
		return fmt.Errorf("model does not have a '%s' field", fieldName)
	}
	// 检查字段是否可设置
	if !field.CanSet() {
		return fmt.Errorf("the '%s' field is not settable", fieldName)
	}

	// 将传入的值转换为反射值
	valueReflect := reflect.ValueOf(value)
	// 检查值的类型是否与字段类型匹配
	if !valueReflect.Type().AssignableTo(field.Type()) {
		// 尝试进行类型转换
		switch field.Type().Kind() {
		case reflect.Uint:
			if valueReflect.Type().Kind() == reflect.String {
				strVal := valueReflect.String()
				if strVal != "" {
					uint64Val, err := strconv.ParseUint(strVal, 10, 64)
					if err != nil {
						return fmt.Errorf("unable to convert string '%s' to uint: %v", strVal, err)
					}
					convertedValue := uint(uint64Val)
					valueReflect = reflect.ValueOf(convertedValue)
				} else {
					valueReflect = reflect.ValueOf(uint(0))
				}

			} else {
				return fmt.Errorf("value type %v is not assignable to the '%s' field of type %v",
					valueReflect.Type(), fieldName, field.Type())
			}
		default:
			return fmt.Errorf("value type %v is not assignable to the '%s' field of type %v",
				valueReflect.Type(), fieldName, field.Type())
		}
	}

	// 设置字段的值
	field.Set(valueReflect)
	return nil
}
func LoadRouteConfigs() ([]interface{}, error) {
	file, err := os.Open("router.json")
	if err != nil {
		return nil, err
	}
	defer file.Close()

	var configs []interface{}
	err = json.NewDecoder(file).Decode(&configs)
	if err != nil {
		return nil, err
	}
	return configs, nil
}

func parseRouteConfig(cfg interface{}) (RouteConfig, error) {
	data, err := json.Marshal(cfg)
	if err != nil {
		return RouteConfig{}, err
	}
	var routeCfg RouteConfig
	err = json.Unmarshal(data, &routeCfg)
	if err != nil {
		return RouteConfig{}, err
	}
	return routeCfg, nil
}

func createHandler(cfg RouteConfig) fiber.Handler {
	return HandleResponse(func(c *fiber.Ctx) (interface{}, error) {
		params := make(map[string]interface{})
		for _, param := range cfg.Params {
			if param.Source == "query" {
				params[param.Name] = c.Query(param.Name)
			} else if param.Source == "body" {
				params[param.Name] = c.Body()
			}
		}

		// 根据配置中的 Model 名称创建模型实例
		model, err := createModelInstance(cfg.Model)
		if err != nil {
			return nil, fiber.NewError(fiber.StatusBadRequest, err.Error())
		}
		switch cfg.Operation {
		case "find":
			if len(params) != 0 {
				for _, param := range cfg.Params {
					if param.Source == "query" && param.Enable {
						if err := setModelField(model, param.Name, params[param.Name]); err != nil {
							return nil, fiber.NewError(fiber.StatusBadRequest, err.Error())
						}
					}
				}
				r, _ := dao.GetList(model)
				return r, nil
			} else {
				r, err := dao.GetAll(model)

				if err != nil {
					return nil, err
				}
				return r, nil
			}
		case "create":
			if err := json.Unmarshal(params["body"].([]byte), model); err != nil {
				return nil, fiber.NewError(fiber.StatusBadRequest, err.Error())
			}
			err := dao.InsertOne(model)
			if err != nil {
				return nil, fiber.NewError(fiber.StatusInternalServerError, err.Error())
			}
			return "增加成功", nil
		case "update":
			if err := json.Unmarshal(params["body"].([]byte), model); err != nil {
				return nil, fiber.NewError(fiber.StatusBadRequest, err.Error())
			}
			err := dao.UpdateOne(model)
			if err != nil {
				return nil, fiber.NewError(fiber.StatusInternalServerError, err.Error())
			}
			return "更新成功", nil
		case "delete":
			if len(params) != 0 {
				for _, param := range cfg.Params {
					if param.Source == "query" && param.Enable {
						if err := setModelField(model, param.Name, params[param.Name]); err != nil {
							return nil, fiber.NewError(fiber.StatusBadRequest, err.Error())
						}
						if err != nil {
							return nil, err
						}
					}
				}
				if err := dao.DeleteOne(model); err != nil {
					return nil, err
				}
				return "删除成功", nil
			}
		}
		return nil, fiber.NewError(fiber.StatusNotImplemented, "未实现的操作")
	})
}

// registerRoute 注册路由
func registerRoute(target interface{}, cfg RouteConfig, handler fiber.Handler) {
	var router interface {
		Get(string, ...fiber.Handler) fiber.Router
		Post(string, ...fiber.Handler) fiber.Router
		Put(string, ...fiber.Handler) fiber.Router
		Delete(string, ...fiber.Handler) fiber.Router
	}

	switch t := target.(type) {
	case *fiber.App:
		router = t
	case *fiber.Group:
		router = t
	default:
		panic("unsupported target type")
	}

	switch strings.ToUpper(cfg.Method) {
	case "GET":
		router.Get(cfg.Path, handler)
	case "POST":
		router.Post(cfg.Path, handler)
	case "PUT":
		router.Put(cfg.Path, handler)
	case "DELETE":
		router.Delete(cfg.Path, handler)
	}
}
